Go Programming - Basics

Concepts of Programming Languages

Sebastian Macke, Stefan Langer

Rosenheim Technical University

Organisational matters

2

Characteristics of a Successful Language (Suggestion)

3

What is an Orthogonal language

4

Types VS. Functions (Non-Orthogonal Design by example)

// Ints are allowed to return
int returnint() {
    return 1;
}

// Structs are allowed to return
typedef struct{} structdef;
structdef returnstruct() {
    structdef mystruct;
    return mystruct;
}

// Arrays are not allowed to return
int[3] returnarray() {
    static int myarray[3] = {1, 2, 3};
    return myarray;
}
5

Other non-orthogonal examples

-- Go doesn't allow this operation.

-- In Go, there is only one loop: for

int x; // x is a value
MyClass y; // y is a reference

-- Go has pointers and values. But the way they are stored is the same.

6

Golang

7

Golang

8

Tools

go env Print Go environment information

go run file.go just runs the code. Can be multiple files, too.

go build downloads dependencies and builds the executable, but needs a go.mod file.

go tool dist list list all supported platforms

env GOOS=darwin GOARCH=arm64 go build Build for Apple ARM CPU computers.

go fmt formats your files

go mod init creates a go.mod module file

go mod tidy updates the go mod file if you add more dependencies

9

Packages

package main

import (
    "fmt"
)

func main() {
    fmt.Printf("Hello %s", "Programming with Go \xE2\x98\xAF\n") // \xE2\x98\xAF -> ☯
    fmt.Printf("Hello %s", "Programming with Go ☯\n")
}
10

Primitive Types

Golang Java Comment
bool boolean
string String
int machine-sized in Go
int8 byte
int16 short
int32 int
int64 long
uint - unsigned int
uint8 -
uint16 -
uint32 -
uint64 -
uintptr -
byte - alias for uint8
rune char alias for int32, represents a Unicode code point. In Java usually 2 bytes.
float32 float
float64 double
complex64 // complex
complex128
struct {x,z,y int} class
11

Complex Numbers

package main

import (
    "fmt"
    "math/cmplx"
)

func main() {
    c := 3 + 4i
    fmt.Printf("c=%v\n", c)
    r, θ := cmplx.Polar(c) // Go supports variables with unicode characters
    fmt.Printf("r=%v, θ=%v\n", r, θ)
}
12

Weak typing vs. Strong typing I

Languages differ of how serious they handle the type

13

Weak typing vs. Strong typing II

Go uses a strong typing system. But why?

14

Weak typing vs. Strong typing II

15

Where implicit type conversion in C goes wrong

int main() {
    signed int a = -1;
    unsigned int b = 0;

    if (a < b) {
        printf("a ís smaller than b\n");
    }

    return 0;
}
16

Javascript is very creative with type coercion

17

Strong typing in Go

package main

import "fmt"

func main() {
    var a int32 = -1
    var b uint32 = 2

    if a < int32(b) {
        fmt.Printf("a is smaller than b")
    }
}
18

Golang - some details

19

Go has a dynamic type: any

func PrintVariableDetails(v any) {
    typeof := reflect.TypeOf(v)
    fmt.Printf("The variable with type '%s' has the value '%v'\n", typeof.Name(), v)
}

func main() {
    var someValue any
    someValue = 2
    PrintVariableDetails(someValue)

    someValue = "abcd"
    PrintVariableDetails(someValue)

    if tmp, ok := someValue.(string); ok {
        fmt.Println("someValue is a string and has the value", tmp)
    }
}
20

Maps

func countWords(input string) map[string]int {

    // Split the string into words using whitespace as a delimiter
    words := strings.Fields(input)

    // Initialize an empty map to store word counts
    wordCounts := make(map[string]int)

    // Iterate over the words and update the count in the map
    for _, word := range words {
        word = strings.ToLower(word) // Convert word to lowercase to ensure case-insensitivity
        wordCounts[word]++           // Increment the count for this word
    }

    return wordCounts
}
21

Arrays and Slices

arr := [5]int{1, 2, 3, 4, 5}

s := arr[0:2]

fmt.Println(len(s), cap(s)) // ==> 2, 5

s = append(s, 8)
s = append(s, 9)
s = append(s, 10)
s = append(s, 11)

fmt.Println(len(s), cap(s)) // ==> 6, 10
22

Functions and Control Structures: Example Palindrome

// IsPalindrome implementation. Does only work for 1-Byte UTF-8 chars (ASCII).
func IsPalindrome(word string) bool {
    for pos := 0; pos < len(word)/2; pos++ {
        if word[pos] != word[len(word)-pos-1] {
            return false
        }
    }
    return true
}
23

Go directly supports Unit Tests via "go test"

// palindrome_test.go
func TestPalindrome(t *testing.T) {
    if !IsPalindrome("") {
        t.Error("isPalindrome('' should be true. But is false.")
    }
    if !IsPalindrome("o") {
        t.Error("isPalindrome('o' should be true. But is false.")
    }
    if !IsPalindrome("oto") {
        t.Error("isPalindrome('oto' should be true. But is false.")
    }
    if IsPalindrome("ottos") {
        t.Error("isPalindrome('ottos' should be false. But is true.")
    }
}
24

Functions and Control Structures: Example Palindrome (UTF-8)

// IsPalindrome2 is using runes. This works for all UTF-8 chars (SBC, MBC).
func IsPalindrome2(word string) bool {
    var runes = []rune(word)
    for pos, ch := range runes {
        if ch != runes[len(runes)-pos-1] {
            return false
        }
    }
    return true
}
pos, ch := range runes
25

Functions and Control Structures: Example Palindrome (Reverse)

// IsPalindrome3 is implemented by reusing Reverse(). Reverse works for UTF-8 chars.
func IsPalindrome3(word string) bool {
    return strings.Reverse(word) == word
}
26

Pointers

27

Pointer I

A pointer is a variable which contains a memory address

func main() {
    var num int = 42
    ptr := &num
    
    fmt.Println("Value of num:", num)           
    // Expected Output: Value of num: 42
    
    fmt.Println("Address of num:", &num)        
    // Expected Output: Address of num: 0xSOME_MEMORY_ADDRESS (this will vary every run)
    
    fmt.Println("Value via pointer:", *ptr)     
    // Expected Output: Value via pointer: 42
    
    fmt.Println("Address stored in ptr:", ptr)  
    // Expected Output: Address stored in ptr: 0xSOME_MEMORY_ADDRESS (same as address of num)
}
28

Pointer I

func swap0(x, y int) (int, int) {
    return y, x
}
func swap1(x, y int) {
    x, y = y, x
}
func swap2(x *int, y *int) {
    *x, *y = *y, *x
}
func swap3(x **int, y **int) {
    *x, *y = *y, *x
}
29

Pointer II

func main() {
    var a, b = 1, 2
    fmt.Printf("Initial : a=%d, b=%d\n", a, b)

    a, b = b, a
    fmt.Printf("After a,b = b,a : a=%d, b=%d\n", a, b)

    swap0(a, b)
    fmt.Printf("After swap0(a,b) : a=%d, b=%d\n", a, b)

    a, b = swap0(a, b)
    fmt.Printf("After a,b = swap0(a,b) : a=%d, b=%d\n", a, b)

    swap1(a, b)
    fmt.Printf("After swap1(a,b) : a=%d, b=%d\n", a, b)

    swap2(&a, &b)
    fmt.Printf("After swap2(&a,&b) : a=%d, b=%d\n", a, b)

    pa, pb := &a, &b
    swap3(&pa, &pb)
    fmt.Printf("After swap3(&pa, &pb): a=%d, b=%d, *pa=%v, *pb=%v\n", a, b, *pa, *pb)
}
30

Exercise 2.1

31

Maps and Slices - Example Book Index

// Page contains an array of words.
type Page []string

// Book is an array of pages.
type Book []Page

// Index contains a list of pages for each word in a book.
type Index map[string][]int

// MakeIndex generates an index structure
func MakeIndex(book Book) Index {
    idx := make(Index)
    for i, page := range book {
        for _, word := range page {
            pages := idx[word]
            idx[word] = append(pages, i)
        }
    }
    return idx
}
32

Stringer Interface

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func (p Person) String() string {
    return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}

func main() {
    person := Person{"Alice", 30}
    fmt.Println(person)
}
33

The Flag API simplifies Command Line Utilities

import (
    "flag"
    "fmt"
)

// Simple test for the Go flag API.
func main() {
    // construct a string flag with a default ip address and a description.
    ip := flag.String("ip", "192.168.1.1", "Overrides the default IP address.")
    port := flag.String("port", "8080", "Overrides the default listen port.")
    flag.Parse()

    fmt.Println("\nDefault value for IP: " + *ip)
    fmt.Println("\nDefault value for port: " + *port)
}
34

Summary

35

Exercise 2.2

36

Thank you

Sebastian Macke, Stefan Langer

Rosenheim Technical University

Use the left and right arrow keys or click the left and right edges of the page to navigate between slides.
(Press 'H' or navigate to hide this message.)